package com.github.ilioili.justdoit.model.dao;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.os.Looper;

import com.github.ilioili.justdoit.model.pojo.EventRecord;
import com.github.ilioili.justdoit.model.pojo.ScheduleEvent;
import com.github.ilioili.justdoit.util.DateRepeatUtil;
import com.github.ilioili.justdoit.util.DateUtil;
import com.github.ilioili.justdoit.util.sql.DbUtil;
import com.github.ilioili.justdoit.util.sql.SqlCallback;
import com.github.ilioili.justdoit.util.sql.SqlUtil;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * Created by hantuo on 16/5/11.
 */
public class ScheduleEventDao extends BaseDao {


    public static ScheduleEvent getById(long id) {
        return DbUtil.getItem(id, ScheduleEvent.class);
    }

    public static void getRountineScheduleEvents(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                List<ScheduleEvent> list;
                try {
                    String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isRepeat = 'true'");
                    Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                    list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                } catch (Exception e) {
                    e.printStackTrace();
                    list = new ArrayList<>();
                }
                post(callback, list);
            }
        }).start();

    }

    public static void delete(ScheduleEvent scheduleEvent) {
        SQLiteDatabase db = DbUtil.getDb();
        try {
            String deleteHabitSql = SqlUtil.getSqlForDelete(scheduleEvent);
            String deleteRecord = SqlUtil.getSqlForDeleteByCondition(EventRecord.class, "_eventId = " + scheduleEvent.id);
            db.beginTransaction();
            db.execSQL(deleteHabitSql);
            db.execSQL(deleteRecord);
            db.setTransactionSuccessful();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
        }
    }

    public static void replace(ScheduleEvent scheduleEvent) {
        DbUtil.replace(scheduleEvent);
    }

    public static void getEventOfToday(final SqlCallback<List<ScheduleEvent>> callback) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    long todayStartTime = DateUtil.getTodayStartTime();
                    long todayEndTime = DateUtil.getTodayStartTime() + DateUtil.DAY_MILISECOND - 1;
                    String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _startTime < " + todayEndTime + " or _startTime between " + todayStartTime + " AND " + todayEndTime + " order by _startTime asc");
                    Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                    List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                    final List<ScheduleEvent> todayList = new ArrayList<>();
                    Date date = Calendar.getInstance().getTime();
                    for (ScheduleEvent scheduleEvent : list) {
                        if (!scheduleEvent.isRepeat) {
                            todayList.add(scheduleEvent);
                        } else if (DateRepeatUtil.matchTheDay(scheduleEvent.repeatFlag, date)) {
                            todayList.add(scheduleEvent);
                        }
                    }
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                callback.onSucess(todayList);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                    post(callback, todayList);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static void getUncompleteEventOfCategory(final String categoryId, final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _categoryId = '" + categoryId + "'");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }


    public static List<ScheduleEvent> getRepeatEvent() {
        String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isRepeat = 'true' order by _createTime asc");
        Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
        List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
        return list;
    }

    public static List<ScheduleEvent> getScheduleEventByName(String name) {
        String sql = null;
        if(name==null){
            sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_categoryId IS NULL ORDER BY _isComplete , _startTime ASC");
        }else{
            sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_categoryId NOT NULL AND _categoryId = '"+name+"' ORDER BY _isComplete , _startTime ASC");
        }
        Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
        List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
        return list;
    }

    public static List<ScheduleEvent> getNeedAlarmEvent() {
        String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_alarm = 'true' AND _isComplete = 'false'");
        Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
        List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
        return list;
    }

    public static void getTodayUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _startTime < " + DateUtil.getTodayEndTime() + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getTomorrowUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long startTime = DateUtil.getTodayEndTime();
                long endTime = startTime + DateUtil.DAY_MILISECOND;
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _startTime >= " + startTime + " AND _startTime <" + endTime + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getAfterTomorrowUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long startTime = DateUtil.getTodayEndTime() + DateUtil.DAY_MILISECOND;
                long endTime = startTime + DateUtil.DAY_MILISECOND;
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _startTime >= " + startTime + " AND _startTime <" + endTime + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getThisWeekUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _startTime < " + DateUtil.getWeekEndTime() + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getNextWeekUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long startTime = DateUtil.getWeekEndTime();
                long endTime = startTime + DateUtil.DAY_MILISECOND * 7;
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _startTime >= " + startTime + " AND _startTime <" + endTime + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getAfterNextWeekUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long startTime = DateUtil.getWeekEndTime() + DateUtil.DAY_MILISECOND * 7;
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _startTime >= " + startTime + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getAllUncompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getAllUncompleteEventByImportance(final int importance, final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='false' AND  _isRepeat='false' AND _importance = " + importance + " order by _startTime asc");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void get100CompleteEvent(final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, "_isComplete='true' AND  _isRepeat='false' order by _startTime asc limit 100");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }


    public static void getAllMatchedEvents(final String s, final SqlCallback<List<ScheduleEvent>> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String sql = SqlUtil.getSqlForSelectWithCondition(ScheduleEvent.class, " _name LIKE '%" + s + "%' OR _categoryId LIKE '%"+s+"%' ORDER BY _isComplete");
                Cursor cursor = DbUtil.getDb().rawQuery(sql, null);
                List<ScheduleEvent> list = DbUtil.getItemList(ScheduleEvent.class, cursor);
                post(callback, list);
            }
        }).start();
    }

    public static void getCompleteCount(final SqlCallback<Integer> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                post(callback, DbUtil.getCount(ScheduleEvent.class, "_isComplete = 'true'"));
            }
        }).start();
    }

    public static void getCompleteTotalTime(final SqlCallback<Integer> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Cursor cursor = DbUtil.getDb().rawQuery("SELECT SUM(_timeSpent) FROM "+SqlUtil.getTableName(ScheduleEvent.class)+" WHERE _isComplete = 'true'", null);
                cursor.moveToFirst();
                int sum = cursor.getInt(0);
                post(callback, sum);
            }
        }).start();
    }

    public static void getRecentHalfMonthData(final SqlCallback<int[]> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int[] data = new int[15];
                long startTime = DateUtil.getTodayStartTime();
                for(int i=0; i<15;i++){
                    long s = startTime-i*DateUtil.DAY_MILISECOND;
                    long e = s+DateUtil.DAY_MILISECOND;
                    data[14-i] = DbUtil.getCount(ScheduleEvent.class, "_startTime >= "+s+" AND _startTime < "+e);
                }
                post(callback, data);
            }
        }).start();
    }
}
